String.prototype.fillStr = function(targetLength, padString) {
    // 获取字符串和填充字符串的长度
    var str = this;
    var padStr = String(typeof padString !== 'undefined' ? padString : ' ');
    var targetLength = Number(targetLength) >> 0; // 转换为正整数
    var padLength = targetLength - str.length; // 计算需要填充的长度
    // 如果targetLength小于等于原字符串长度或者填充字符串为空，则返回原字符串
    if (targetLength <= str.length || padString === null) {
        return String(str);
    }
    // 循环填充字符串直到达到目标长度
    while (padLength > padStr.length) {
        padStr += padStr; // 如果填充字符串长度不够，则重复使用它直到足够长
    }
    // 返回填充后的字符串
    return padStr.slice(0, padLength) + String(str);
};
var Utils = (function (dom) {
    return {
        baseUrl: 'http://192.168.31.226:9081',
        useLocalEvent: true,
        getSubQueue: function (subQueueFlag) {
            // 后面要查询接口，从后端读取
            var subQueueMap = [
                {label: '预约', nick: '预', value: 2}
            ]
            var currentSubQueue = subQueueMap.find(item => item.value === subQueueFlag)
            return currentSubQueue || null
        },
        formatPatientName: function (name) {
            if (name && name.length > 2) {
                return name.substring(0, 1) + '☆' + name.substring(name.length - 1, name.length)
            } else if (name && name.length >= 1) {
                return name.substring(0, 1) + '☆'
            }
            return ''
        },
        getQueryParams: function(url) {
            var splitCharIndex = url.indexOf('?');
            var params = {};
            if (splitCharIndex > 0) {
                var paramsStrArr = url.substring(splitCharIndex + 1).split('&');
                paramsStrArr.forEach(paramsStr => {
                    var paramName = paramsStr.split('=')[0];
                    params[paramName] = paramsStr.split('=')[1];
                });
            }
            return params;
        },

        findMaxRepeatedSubstring: function(str) {
            if (str.length >= 10) {
                if (str.length % 3 === 0) {
                    var firstStr = str.substring(0, str.length / 3)
                    var secondStr = str.substring(str.length / 3, 2 * (str.length / 3))
                    var thirdStr = str.substring(2 * (str.length / 3))
                    if (firstStr === secondStr && thirdStr === secondStr) {
                        return firstStr
                    }
                }
                else if (str.length % 2 === 0) {
                    var firstStr = str.substring(0, str.length / 2)
                    var secondStr = str.substring(str.length / 2)
                    if (firstStr === secondStr) {
                        return firstStr
                    }
                }
            }
            return str;
        },
        typeOf: function(obj) {
            var toString = Object.prototype.toString;
            var map = {
                '[object Boolean]': 'boolean',
                '[object Number]': 'number',
                '[object String]': 'string',
                '[object Function]': 'function',
                '[object Array]': 'array',
                '[object Date]': 'date',
                '[object RegExp]': 'regExp',
                '[object Undefined]': 'undefined',
                '[object Null]': 'null',
                '[object Object]': 'object',
            };
            return map[toString.call(obj)];
        },
        formatDate: function (date, formatter) {
            try {
                formatter = formatter || 'yyyy-MM-dd HH:mm:ss'
                var _currentDate = this.typeOf(date) === 'number' || this.typeOf(date) === 'string' ? new Date(date) : date
                var hours = _currentDate.getHours()
                var minutes = _currentDate.getMinutes()
                var second = _currentDate.getSeconds()

                var year = _currentDate.getFullYear()
                var month = _currentDate.getMonth() + 1
                var date = _currentDate.getDate()

                var dateArr = [
                    year,
                    month.toString().fillStr(2, '0'),
                    date.toString().fillStr(2, '0'),
                    hours.toString().fillStr(2, 0),
                    minutes.toString().fillStr(2, '0'),
                    second.toString().fillStr(2, 0)
                ]
                if (formatter === 'HH:mm') {
                    return dateArr.slice(3, 5).join(":");
                } else if (formatter === 'MM-dd') {
                    return dateArr.slice(1, 3).join("-");
                } else {
                    return dateArr.slice(0, 3).join("-") +" "+ dateArr.slice(3).join(":");
                }
            }catch (e){}
            return ''
        },
        matchCount: function (mainString, substring) {
            var regex = new RegExp(substring, 'g');
            var matches = mainString.match(regex);
            return matches ? matches.length : 0;
        },
        request: function (url, method, data, callback) {
            // 创建一个新的 XMLHttpRequest 对象
            var xhr = new XMLHttpRequest();
            // 设置请求类型和方法
            xhr.open(method, url, true);
            // 监听请求状态变化
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    // 请求成功，调用回调函数并传入响应数据
                    callback(null, JSON.parse(xhr.responseText));
                } else if (xhr.readyState === 4) {
                    // 请求失败，调用回调函数并传入错误信息
                    callback(xhr.statusText, null);
                }
            };
            // 设置请求头（如果需要）
            xhr.setRequestHeader('Content-Type', 'application/json');
            // 发送请求
            if (method && 'POST,PUT'.includes(method.toUpperCase())) {
                // 发送 POST 请求，并传入数据
                xhr.send(data);
            } else {
                // 发送 GET 请求
                xhr.send();
            }
        },
        resetFontSize: function(width, height){
            var baseWidth = width || 1920
            var baseHeight = height || 1080
            var baseFontSize = 100
            var clientWidth = dom.body.clientWidth
            var fontSize = Math.min((clientWidth / baseWidth) * baseFontSize, 100) + 'px'
            document.querySelector('html').style.fontSize = fontSize
        }
    }
})(document)

var Api = (function (Utils) {
    return {
        getDevice: function (clientId, _successCallback) {
            var params = Utils.getQueryParams(window.location.href)
            var clientType = params.client_type
            var requestUrl = Utils.baseUrl + '/sse/open/connect' + '?client_type=' + clientType || 'call_web'
            Utils.request(requestUrl, "GET", null, function(error, res) {
                if (!error && res) {
                    if (_successCallback) {
                        _successCallback(res)
                    }
                }
            })
        },
        heartbeat: function(callback) {
            var requestUrl = Utils.baseUrl + '/sse/heartbeat/connect'
            Utils.request(requestUrl, 'get', null ,function (error, res) {
                if (!error && res && res.data) {
                    if (callback) {
                        callback(res.data)
                    }
                }
            })
        },
        listRoom: function (deviceId, callback) {
            Utils.request(Utils.baseUrl + '/queue/device/' + deviceId + '/connect/room/list', 'get', null, function(error, res) {
                callback(res)
            })
        },
        listPassedPatient: function (deviceId, callback) {
            Utils.request(Utils.baseUrl + '/queue/device/' + deviceId + '/passed/patient/list', 'get', null, function(error, res) {
                callback(res)
            })
        }
    }
})(Utils)

var DateTimeRender = (function(Utils, win){
    var _interval = null
    var _currentDate = new Date()
    var _currentTimestamp = 0
    var _oldTimestamp = 0
    var _weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
    var _dateTimeEle = null
    var _sendServerTimeout = 60
    var _renderFun = null

    var _startIntervalTime = function () {
        _interval = setInterval(function() {
            if (_currentTimestamp > 0) {
                _currentTimestamp += 1000
                _currentDate = new Date(_currentTimestamp)
            } else {
                _currentDate = new Date();
                _oldTimestamp = _currentDate.getTime();
                _currentTimestamp = _currentDate.getTime()
            }
            _generatorDate()
            if (_sendServerTimeout === 0) {
                _sendServerTimeout = 60
                _checkServerTime()
            }
            _sendServerTimeout--
        }, 1000)
    }


    var _clearIntervalTime = function () {
        if (_interval) {
            clearInterval(_interval)
        }
    }

    var _checkServerTime = function () {
        Api.heartbeat(function (datetime) {
            _oldTimestamp = new Date(datetime).getTime()
            _currentTimestamp = _oldTimestamp
        })
    }

    var _generatorDate = function () {
        var hours = _currentDate.getHours()
        var minutes = _currentDate.getMinutes()
        var second = _currentDate.getSeconds()

        var timeStr = [hours.toString().fillStr(2, '0'), minutes.toString().fillStr(2, '0'), second.toString().fillStr(2, '0')].join(":")

        var year = _currentDate.getFullYear()
        var month = _currentDate.getMonth() + 1
        var date = _currentDate.getDate()

        var dateStr = month.toString().fillStr(2, '0') + '月' + date.toString().fillStr(2, '0') + '日'

        var weekIndex = _currentDate.getDay()
        var weekStr = _weeks[weekIndex];
        if (_dateTimeEle) {
            _dateTimeEle.innerText = (dateStr + " " + weekStr + " " + timeStr)
        }

        // 定时强刷一次页面
        // if ([12, 18, 23].includes(hours) && minutes === 30) {
        //     window.location.reload()
        // }

        if (_renderFun) {
            _renderFun([year,
                    month.toString().fillStr(2, '0'),
                    date.toString().fillStr(2, '0'),
                    hours.toString().fillStr(2, 0),
                    minutes.toString().fillStr(2, '0'),
                    second.toString().fillStr(2, 0)],
                weekStr
            )
        }
    }

    return {
        render: function (dateTimeEle, renderFun) {
            _dateTimeEle = dateTimeEle
            _renderFun = renderFun
            _checkServerTime()
            _startIntervalTime()
        }
    }
})(Utils, window)
var TTS = (function (win) {
    var _speechTextArr = []
    var _isSpeeching = false
    return {
        sayMessages: function(messages, config) {
            if (messages && messages.length) {
                for(var message of messages) {
                    var speech = new SpeechSynthesisUtterance(message)
                    speech.onend = TTS.onSpeechEnd
                    _speechTextArr.push(speech)
                }
            }
            if (!_isSpeeching) {
                TTS.onSpeech()
            }
        },
        onSpeechEnd: function () {
            _isSpeeching = false
            if (_speechTextArr && _speechTextArr.length) {
                TTS.onSpeech()
            }
        },
        onSpeech: function () {
            if (!_isSpeeching) {
                _isSpeeching = true
                var speechText = _speechTextArr[0]
                _speechTextArr.splice(0, 1)
                win.speechSynthesis.speak(speechText);
            }

        }
    }

})(window)
var WebSocketClient = (function (Utils) {
    var ws = null, ipAddress = '', wsTimeout = null;
    var _successCallback = null
    return {
        init(ip, successCallback) {
            var url = Utils.baseUrl && Utils.baseUrl.indexOf("http") === 0 ? "ws" + Utils.baseUrl.substring(Utils.baseUrl.indexOf("://")) : "";
            ipAddress = ip
            _successCallback = successCallback
            console.log('start websocket connect!!!', ip, url, window.location.href)
            ws =  new WebSocket(url + "/socket/connect?wsId="+ip+"&app_secret=123")
            var timeout = setTimeout(function() {
                ws.close();
            }, 5000); // 设置超时时间为5秒

            ws.onopen = function () {
                clearTimeout(timeout)
                console.log('================websocket open================', url)
                ws.send(JSON.stringify({
                    action: 'heartbeat',
                    data: null
                }))
                setInterval(function () {
                    ws.send(JSON.stringify({
                        action: 'heartbeat',
                        data: null
                    }))
                }, 30000)
            }
            ws.onmessage = function (event) {
                console.log('================websocket onmessage================', event.data, JSON.stringify(event.data))
                if (successCallback) {
                    successCallback(1, event.data)
                }
            }
            ws.onerror = function (event) {
                if (successCallback) {
                    successCallback(0, null)
                }
                clearTimeout(timeout)
                if (wsTimeout) {
                    clearTimeout(wsTimeout)
                    wsTimeout = null
                }
                console.log('================websocket onerror================', url)
                wsTimeout = setTimeout(function () {
                    WebSocketClient.init(ip, successCallback)
                }, 15000)
            }
            ws.onclose = function () {
                if (successCallback) {
                    successCallback(0, null)
                }
                clearTimeout(timeout)
                if (wsTimeout) {
                    clearTimeout(wsTimeout)
                    wsTimeout = null
                }
                wsTimeout = setTimeout(function () {
                    WebSocketClient.init(ip, successCallback)
                }, 15000)
                console.log('=============websocket onclose-------------', url)
            }
        }
    }
})(Utils)

var SSEUtils = (function (Utils) {
    var _sseOpenConnectUrl = "/sse/open/connect"
    var _sseCloseConnectUrl = "/sse/close/connect"
    var _eventSource = null
    var _isConnected = false
    var _clientId = ''
    var _sseInterval = null

    return {
        open: function (clientId, _successCallback) {
            console.log('sse open:::', clientId)
            var that = this
            if (!_eventSource) {
                var params = Utils.getQueryParams(window.location.href)
                var clientType = params.client_type
                var _sseUrl = _sseOpenConnectUrl + '?client_type=' + clientType || 'call_web'
                console.log('start sse open:::', _sseOpenConnectUrl)
                _eventSource = new EventSource(Utils.baseUrl + _sseUrl, null);
                _clientId = clientId
                _eventSource.onopen = () => {
                    _isConnected = true
                    console.log(' sse opened')
                }
                _eventSource.onerror = (error) => {
                    console.log(' sse error:::', error)
                    if (window.Android && window.Android.addLogs) {
                        window.Android.addLogs("【"+Utils.formatDate(new Date())+"】SSE: 连接出现错误!")
                    }
                    if (_sseInterval) {
                        clearTimeout(_sseInterval)
                        _sseInterval = null
                    }
                    try {
                        that.stop()
                    }catch (e) {}
                    if (window.Android && window.Android.addLogs) {
                        window.Android.addLogs("【"+Utils.formatDate(new Date())+"】SSE: 连接出现错误后30s后重新连接!")
                    }
                    _sseInterval = setTimeout(function () {
                        that.open(clientId, _successCallback)
                    }, 30000)
                }
                _eventSource.onmessage = (event) => {
                    console.log(' sse message:::', event.data)
                    let data = {}, isParseErr = false
                    try { data = JSON.parse(event.data) } catch (e) {
                        isParseErr = true
                    }
                    if (window.Android && window.Android.addLogs) {
                        window.Android.addLogs("【"+Utils.formatDate(new Date())+"】SSE: 获取到消息：" + event.data + ", parse error:" + isParseErr)
                    }
                    if (_successCallback) {
                        _successCallback(data)
                    }
                }
            }
        },
        stop: function () {
            if (_eventSource) {
                _eventSource.close()
                _eventSource = null
            }
            if (_isConnected) {
                var params = Utils.getQueryParams(window.location.href)
                var clientType = params.client_type
                _sseCloseConnectUrl += '?client_type=' + clientType || 'call_web'
                Utils.request(Utils.baseUrl + _sseCloseConnectUrl, 'post', null, function(isError, data) {
                    if (!isError && data && data.code === 200 && _eventSource) {}
                })
            }
            _isConnected = false
        }
    }
})(Utils)
// 呼叫弹窗
var CallDialog = (function (Utils, TTS) {
    var _show = false
    var _messages = []
    var _deviceRoom = null
    var _broadcastEngine = TTS
    var showDialog = function () {
        if (_messages && _messages.length > 0) {
            _show = true
            var message = _messages[0]
            var dialog = document.querySelector('div#yy-screen-just-call')
            dialog.querySelector('div.yy-screen-just-call__message').innerHTML = getMessageTemp(message)
            dialog.removeAttribute("style")
            // console.log('---------device room--------', _deviceRoom)
            var config = {}
            try {
                config = _deviceRoom && _deviceRoom.device ? JSON.parse(_deviceRoom.device.config) : {}
            }catch (ex) {}
            // 语音广播
            _broadcastEngine.sayMessages([getTTSMessageTemp(message)], config)
            _messages.splice(0, 1)
            setTimeout(function() {
                showDialog()
            }, 6000)
        } else {
            _show = false
            document.querySelector('div#yy-screen-just-call').setAttribute("style", "display: none;")
        }
    }
    var getMessageTemp = function (data) {
        var subQueue = Utils.getSubQueue(data.subQueueFlag)
        return `
                 <div>请${!!subQueue ? (" " + subQueue.nick + " ") : (data.registerNo + '号')}${Utils.formatPatientName(data.patientName)}</div>
                 <div class='scroll-text-box'> <div class='scroll-text-wrapper'> <div class='scroll-text-item'> 到${data.roomName}就诊</div></div> </div>
            `
    }
    var getTTSMessageTemp= function (params, template) {
        params.roomName = params.roomName ? params.roomName : "";
        var subQueue = Utils.getSubQueue(params.subQueueFlag)
        var defaultTemplate = `请${!!subQueue ? subQueue.label : "#{registerNo}号"}#{patientName}到#{roomName}就诊`
        var messageTemplate = template ? template : defaultTemplate
        var paramKeys = messageTemplate.match(/#\{[a-z0-9A-Z_]+\}/g)
        if (paramKeys.length) {
            for(var par of paramKeys) {
                var paramKey = par.substring(2, par.length - 1)
                var parReg = new RegExp(par, 'ig')
                messageTemplate = messageTemplate.replace(parReg, params[paramKey])
            }
        }
        return messageTemplate
    }

    return {
        setConnectDevice: function (deviceRoom) {
            if (deviceRoom) {
                _deviceRoom = deviceRoom
            }
            return this
        },

        setBroadcastEngine: function (broadcastEngine) {
            if (broadcastEngine) {
                _broadcastEngine = broadcastEngine
            }
            return this
        },
        show: function (data) {
            var message = {
                registerNo: data.just[data.just.length - 1].registerNo,
                patientName: data.just[data.just.length - 1].patientName,
                roomName: data.roomName,
                itemName: data.just[data.just.length - 1].itemName,
                subQueueFlag: data.just[data.just.length - 1].subQueueFlag
            }
            //弹窗显示
            _messages.push(message)
            if (!_show) {
                showDialog()
            }
        }
    }
})(Utils, TTS)